#include "WebKit.h"

namespace SpiderWebKitClient {
WebKit::WebKit(std::string method, bool isStatic, int type)
    : m_caller(new WebKitCaller())
    , m_isStatic(isStatic)
    , m_type(type)
{
    if (!method.empty())
        m_method = method;
    initCaller();
}

WebKit::~WebKit()
{
    destroyAllPages();
    m_caller.reset();
}

void WebKit::initCaller()
{
    if (m_type == WKMethodTypeDefault)
        m_caller->initDefault(m_method, m_isStatic);
    else if (m_type == WKMethodTypeStaticProtocol)
        m_caller->initWithServerProtocol(m_method, m_isStatic);
}

bool WebKit::isFailed()
{
    return m_caller->failed();
}

ResFilter WebKit::filter()
{
    return m_resFilter;
}

void WebKit::setFilter(ResFilter filter)
{
    m_resFilter = filter;
}

long WebKit::setCookies(std::list<Cookie> cookies, std::string url)
{
    Json::FastWriter writer;
    Json::Value root(Json::arrayValue);
    std::list<std::string> arglist;

    std::list<Cookie>::iterator it;
    for (it = cookies.begin(); it != cookies.end(); it ++)
        root.append(it->content());

    std::string cookiesString = writer.write(root);
    arglist.push_back(cookiesString);
    arglist.push_back(url);
    std::string retMessage = m_caller->webKitCall(0, WEBKIT_LONG_SETCOOKIE_LONG_REF_STRING_COOKIES_STRING_URL, arglist);
    return m_caller->getReturnLongValue(retMessage);
}

WebPage* WebKit::get(std::string url, int level, long timeMS, long destroyTimeMS)
{
    return getWebPage(url, level, timeMS, destroyTimeMS);
}

WebPage* WebKit::get(int &error, std::string url, int level, long timeMS, long destroyTimeMS)
{
    return getWebPage(error, url, level, timeMS, destroyTimeMS);
}

WebPage* WebKit::post(std::string url, std::string data, int level, long timeMS, long destroyTimeMS)
{
    WebPage *page = getWebPage("", level, timeMS, destroyTimeMS);
    
    if (!page)
        return NULL;

    std::map<std::string, std::string> nullHeaders;
    page->loadUrl(url, "POST", true, timeMS, destroyTimeMS, nullHeaders, data, "utf8");
    return page;
}

WebPage* WebKit::post(int &error, std::string url, std::string data, int level, long timeMS, long destroyTimeMS)
{
    WebPage *page = getWebPage(error, "", level, timeMS, destroyTimeMS);

    if (!page)
        return NULL;

    std::map<std::string, std::string> nullHeaders;
    error = page->loadUrl(url, "POST", true, timeMS, destroyTimeMS, nullHeaders, data, "utf8");
    return page;
}

WebPage* WebKit::getWebPage(std::string url, int level, long timeMS, long destroyTimeMS)
{
    int error;
    return getWebPage(error, url, level, timeMS, destroyTimeMS);
}

WebPage* WebKit::getWebPage(int &error, std::string url, int level, long timeMS, long destroyTimeMS)
{
    /* caller失效的错误处理, 重试10次 */
    int times = 0;
    while (isFailed()) {
        times ++;

        if (times > 10) {
            error = -1;
            return NULL;
        }

        m_caller.reset();
        boost::shared_ptr<WebKitCaller> caller(new WebKitCaller());
        m_caller = caller;
        initCaller();

        if (isFailed())
            sleep(1);
    }

	if (url == "")
		url = "about:blank";

    if (!m_caller->checkAvailable()) {
        error = NOTAVALIABLE_LOAD_ERROR;
        return NULL;
    }

    long pageref = 0;
    std::list<std::string> arglist;

    std::string l = boost::lexical_cast<std::string>(level);
    std::string t = boost::lexical_cast<std::string>(timeMS);
    arglist.push_back("0");
    arglist.push_back(url);
    arglist.push_back(m_resFilter.toJson());
    arglist.push_back(l);
    arglist.push_back(t);
    if (destroyTimeMS != -1) {
        std::string dt = boost::lexical_cast<std::string>(destroyTimeMS);
        arglist.push_back(dt);
    }

    std::string retMessage = m_caller->webKitCall(0, WEBKIT_LONG_GET_LONG_REF_STRING_URL, arglist, timeMS + REQUEST_TIMEOUT*5);
    error = m_caller->getReturnPageValue(retMessage, &pageref);

    // spider webkit core need reconnect.
    if (error == DYING_LOAD_ERROR || error == CANCEL_LOAD_ERROR) {
        times = 0;
        while(error == DYING_LOAD_ERROR || error == CANCEL_LOAD_ERROR) {
            times ++;
            if (times >= 10) {
                std::cout << "NOTE : ---- Get Page Failed ---- " << url << std::endl;
                break;
            }
            sleep(1);
            m_caller.reset();
            boost::shared_ptr<WebKitCaller> caller(new WebKitCaller());
            m_caller = caller;

            initCaller();

            std::string retMessage = m_caller->webKitCall(0, WEBKIT_LONG_GET_LONG_REF_STRING_URL, arglist, timeMS + REQUEST_TIMEOUT*5);
            error = m_caller->getReturnPageValue(retMessage, &pageref);
        }
    }

    if (error < 0)
        return NULL;

    WebPage *page = new WebPage(pageref, m_caller, m_pages, m_resFilter);
    m_pages.insert(m_pages.begin(), page);

    return page;
}

long WebKit::destoryWebPage(WebPage *page)
{
    if (!page)
        return -1;

    long ret = 0;
    std::list<std::string> arglist;

    std::list<WebPage*>::iterator it = find(m_pages.begin(), m_pages.end(), page);
    if (it == m_pages.end())
        return -1;

    m_pages.remove(page);
    delete page;

    return ret;
}

void WebKit::destroyAllPages()
{
    if (m_pages.size() <= 0)
        return ;

    long ret = 0;
    std::list<std::string> arglist;
    std::list<WebPage*>::iterator it;

    for (it = m_pages.begin(); it != m_pages.end(); it ++) {
        WebPage *page = (*it);
        delete page;
    }
    m_pages.clear();
}

} //namespace SpiderWebKitClient
